from Bases import BaseObject, setID
from masterclock import Clock

class Sequencer(BaseObject):
    _saved_class_name = 'Sequencer'
    _saved_attributes = ['id', 'name', 'persistent', 'duration', 'mode', 'controllers_id']
    def __init__(self, **kwargs):
        super(Sequencer, self).__init__(**kwargs)
        self.register_signal('state_changed')
        self._state = False
        self.fps = float(kwargs.get('fps', 24))
        self.interval =  self.fps / 1000
        if 'deserialize' not in kwargs:
            self.id = setID(kwargs.get('id'))
            self.name = kwargs.get('name', '')
            self.persistent = kwargs.get('persistent', False)
            self._duration = float(kwargs.get('duration', 2))
            self._mode = kwargs.get('mode', 'single')
            self.controllers_id = set()
        self.clock = kwargs.get('clock')
        if not self.clock:
            self.clock = Clock(interval=self.interval)#, callbacks=[self.on_tick])
        self.controllers = {}
        self.controller_set = set()
        self.start_time = self.clock.seconds
    def add_controller(self, controller):
        self.controllers.update({controller.id:controller})
        self.controller_set.add(controller)
    def del_controller(self, controller):
        if controller.id in self.controllers:
            del self.controllers[controller.id]
        self.controller_set.discard(controller)
    @property
    def state(self):
        return self._state
    @state.setter
    def state(self, value):
        if value != self.state:
            self._state = value
            self.emit('state_changed', obj=self, id=self.id, state=value)
    @property
    def duration(self):
        return self._duration
    @duration.setter
    def duration(self, value):
        self._duration = float(value)
    @property
    def mode(self):
        return self._mode
    @mode.setter
    def mode(self, value):
        self._mode = value
    @property
    def scaled_time(self):
        t = (self.clock.seconds - self.start_time) / self.duration
        #print 'seq: csec=%s, start=%s, duration=%s, t=%s' % (self.clock.seconds, self.start_time, self.duration, t)
        if self.direction:
            return t
        return (t * -1.0) + 1.0
    def get_values_for_time(self, timeV):
        d = {}
        for key, val in self.controllers.iteritems():
            d.update({key:val.calculate_value(timeV)})
        return d
    def start(self, direction=True):
        self.clock.add_callback(self.on_tick)
        self.direction = direction
        self.start_time = self.clock.seconds
        #print 'start'
        self.state = True
        if not self.clock.running:
            self.clock.start()
    def stop(self):
        self.clock.del_callback(self.on_tick)
        self.state = False
    def on_tick(self, clock):
        t = clock.seconds - self.start_time
        scaledT = self.scaled_time
        for c in self.controller_set:
            c.on_interval(scaledT)
        if t >= self.duration:
            self.on_duration_end()
    def on_duration_end(self):
        if self.mode == 'single':
            self.stop()
        elif self.mode == 'updn':
            self.start(direction=not self.direction)
        elif self.mode == 'up':
            self.start()
